﻿/**
* CRL
*/
using CRL.Data;
using CRL.Data.Attribute;
using CRL.Data.LambdaQuery;
using Nest;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using CRL.Data.DBExtend;
namespace CRL.Elasticsearch.ESEx
{
    public sealed partial class ESExtend : AbsDBExtend
    {
        public ESExtend(DbContextInner _dbContext)
            : base(_dbContext)
        {
        }
        protected override ILambdaQuery<TModel> CreateLambdaQuery<TModel>()
        {
            return new ESLambdaQuery<TModel>(dbContext);
        }

        ElasticClient _esClient = null;
        string IndexName;
        ElasticClient getClient()
        {
            if (_esClient == null)
            {
                var db = GetDBHelper() as ESHelper;
                if (db._client != null)
                {
                    return db._client;
                }
                var connectionString = db.ConnectionString;
                IndexName = db.DatabaseName.ToLower();
                //DefaultFieldNameInferrer 索引名按模型大小写
                var setting = new ConnectionSettings(new Uri(connectionString)).DefaultFieldNameInferrer((name) => name).DefaultIndex(IndexName);
                if (db.DBAccessBuild.Data != null)
                {
                    Func<ConnectionSettings, ConnectionSettings> func = db.DBAccessBuild.Data as Func<ConnectionSettings, ConnectionSettings>;
                    func(setting);
                }
                _esClient = new ElasticClient(setting);
            }
            return _esClient;
        }
        public override void CreateTableIndex<TModel>()
        {
            CreateEsIndex<TModel>();
        }
        public void CreateEsIndex<TModel>(Func<CreateIndexDescriptor, ICreateIndexRequest> selector = null) where TModel : class
        {
            var indexState = new IndexState()
            {
                Settings = new IndexSettings()
                {
                    NumberOfReplicas = 1,//副本数
                    NumberOfShards = 5//分片数
                }
            };
            //client.Indices.Create(IndexName, p => p.InitializeUsing(indexState));
            //return;
            var client = getClient();
            if (selector == null)
            {
                selector = p => p.Map<TModel>(x => x.AutoMap<TModel>());
            }
            var result = client.Indices.Create(IndexName, selector);
            Log("CreateIndex", result);
            SetMaxResult(client);
        }
        public override void DropTable<TModel>()
        {
            getClient().Indices.Delete(IndexName);
        }
        int maxSize = 100000;
        public void SetMaxResult(ElasticClient client)
        {
            var req = new UpdateIndexSettingsRequest("_all");
            req.IndexSettings = new DynamicIndexSettings();
            req.IndexSettings.Add("max_result_window", maxSize);
            var result = client.Indices.UpdateSettings(req);
            Log("SetMaxResult", result);
        }
		public override int Update<TModel>(BatchUpdate<TModel> batchUpdate)
		{
			throw new NotImplementedException();
		}
		public override TType GetFunction<TType, TModel>(Expression<Func<TModel, bool>> expression, Expression<Func<TModel, TType>> selectField, FunctionType functionType, bool compileSp = false)
        {
            var query = new ESLambdaQuery<TModel>(dbContext);
            query.Where(expression);
            var m = selectField.Body as MemberExpression;
            var fieldName = m?.Member?.Name;
            object result = null;
            switch (functionType)
            {
                case FunctionType.COUNT:
                    //result = collection.Find(expression).CountDocuments();
                    result = getClient().Count(new CountRequest()
                    {
                        Query = new BoolQuery()
                        {
                            Filter = query.queryContainers,
                        }
                    }).Count;
                    break;
                //case FunctionType.SUM:
                //    result = getAggregateResult(collection, expression, "sum", fieldName);
                //    break;
                //case FunctionType.MAX:
                //    result = getAggregateResult(collection, expression, "max", fieldName);
                //    break;
                //case FunctionType.MIN:
                //    result = getAggregateResult(collection, expression, "min", fieldName);
                //    break;
                default:
                    throw new NotSupportedException("不支持的函数:" + functionType);
            }
            return ObjectConvert.ConvertObject<TType>(result);
        }
    }
}
